# Copyright (c) 2019 Presto Labs Pte. Ltd.
# Author: xguo

import logging
from typing import List, Union

import requests
from tornado import gen

import coin.flow.topic_map as topic_map
from coin.base.timestamp import get_timestamp
from coin.base.param_util import to_list
from coin.exchange.coinone_v2.kr_rest.native_private_client import (
    CoinoneNativePrivateClient,)
from coin.exchange.base.rest.task_scheduler import Scheduler


class CoinoneSubscriber(object):
  def __init__(
      self,
      queue,
      group_id: str,
      worker_id: str,
      symbol: Union[List[str], str],
      close_callback=None,
      logger=None,
  ):
    self._symbols = to_list(symbol)
    assert len(self._symbols) >= 1, self._symbols
    self._publisher = None
    self._scheduler = Scheduler()
    self._init_publisher(queue, group_id, worker_id)
    self._feed_client = CoinoneNativePrivateClient(key_file=None,
                                                   max_connections=20,
                                                   use_async=True)
    self._logger = logger or logging.getLogger(__name__)

  def _init_publisher(self, queue, group_id: str, worker_id: str):
    topic_depth = topic_map.search_topic_id('coinone_rest_depth_%s%s' % (group_id, worker_id))[0]
    topic_trade = topic_map.search_topic_id('coinone_rest_trade_%s%s' % (group_id, worker_id))[0]

    self._publisher = {
        'orderbook': queue.get_writer(topic_id=topic_depth[1]),
        'trades': queue.get_writer(topic_id=topic_trade[1]),
    }

  @gen.coroutine
  def _query_book(self, currency):
    try:
      response = yield self._feed_client.query_orderbook(currency=currency)
    except requests.exceptions.RequestException as exc:
      self._logger.error('query book error: %s', exc.request.url)
      return

    timestamp = get_timestamp()
    if response.status_code == 200:
      message = response.json()
      self._publisher['orderbook'].write(timestamp, message)
    else:
      self._logger.error('query book error! %s', response.status_code)

  @gen.coroutine
  def _query_trade(self, currency):
    try:
      response = yield self._feed_client.query_trades(currency=currency)
    except requests.exceptions.RequestException as exc:
      self._logger.error('query trade error: %s', exc.request.url)
      return

    if response.status_code == 200:
      timestamp = get_timestamp()
      message = response.json()
      self._publisher['trades'].write(timestamp, message)
    else:
      self._logger.error('query trade error! %s', response.status_code)

  def start(self, ioloop, delay_time=0):
    self.stop()
    self._scheduler = Scheduler(ioloop)
    for currency_pair in self._symbols:
      self._scheduler.add_periodic_task(period=1,
                                        job_func=self._query_book,
                                        currency_pair=currency_pair)
      self._scheduler.add_periodic_task(period=1,
                                        job_func=self._query_trade,
                                        currency_pair=currency_pair)
    self._scheduler.start(later_td=delay_time)

  def stop(self):
    if self._scheduler is not None:
      self._scheduler.stop()
